/* eslint-disable regexp/no-super-linear-backtracking */
import type { Plugin } from 'vite'
import fs from 'node:fs'
import path from 'node:path'
import { camelize } from '@vue/shared'
import { docRoot } from '../utils/build-utils'
import { CompsStrToArray } from '../utils/util'

type Append = Record<'headers' | 'footers' | 'scriptSetups', string[]>

export function MarkdownTransform(): Plugin {
  return {
    name: 'element-plus-md-transform',
    enforce: 'pre',
    async buildStart() {},
    async transform(code, id) {
      if (!id.endsWith('.md')) {
        return
      }
      const components = CompsStrToArray(code)
      const componentId = path.basename(id, '.md')
      if (!components.includes(componentId)) {
        components.push(componentId)
      }

      const append: Append = {
        headers: [],
        footers: [],
        scriptSetups: components.reduce((arr, cur) => {
          return [...arr, ...getExampleImports(cur)]
        }, [] as string[]),
        // scriptSetups: getExampleImports(componentId)
      }

      code = transformVpScriptSetup(code, append)

      return combineMarkdown(
        code,
        [combineScriptSetup(append.scriptSetups), ...append.headers],
        append.footers,
      )
    },
  }
}

function combineScriptSetup(codes: string[]) {
  return `
    \n<script setup>
      ${codes.join('\n')}
    </script>
  `
}

function combineMarkdown(code: string, headers: string[], footers: string[]) {
  /* const match = code.match(/^---\n([\s\S]*?)\n---\n?/)
  let sliceIndex = 0
  if (match) {
    sliceIndex = match[0].length
  } else {
    const firstHeader = code.search(/\n#{1,6}\s.+/)
    sliceIndex = firstHeader >= 0 ? firstHeader : 0
  } */

  if (headers.length > 0) {
    // 实在搞不懂为什么element-plus为啥要这么写，导致结构被破坏
    // code = code.slice(0, sliceIndex) + headers.join('\n') + code.slice(sliceIndex)
    code += headers.join('\n')
  }

  code += footers.join('\n')
  return `${code}\n`
}

const vpScriptSetupRE
  = /<vp-script\s(.*\s)?setup(\s.*)?>([\s\S]*)<\/vp-script>/

function transformVpScriptSetup(code: string, append: Append) {
  const matches = code.match(vpScriptSetupRE)
  if (matches)
    code = code.replace(matches[0], '')
  const scriptSetup = matches?.[3] ?? ''
  if (scriptSetup)
    append.scriptSetups.push(scriptSetup)
  return code
}

function getExampleImports(componentId: string) {
  const examplePath = path.resolve(docRoot, 'examples', componentId)
  if (!fs.existsSync(examplePath))
    return []
  const files = fs.readdirSync(examplePath)
  const imports: string[] = []

  for (const item of files) {
    if (!/\.vue$/.test(item))
      continue
    const file = item.replace(/\.vue$/, '')
    const name = camelize(`Ep-${componentId}-${file}`)

    imports.push(
      `import ${name} from '../../examples/${componentId}/${file}.vue'`,
    )
  }
  return imports
}
